package org.NooLab.nativebrowser;

import java.awt.Dimension;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import org.NooLab.nativebrowser.app.config.NNBAppProperties;
import org.NooLab.nativebrowser.app.config.ITexxAppPropertiesIntf;
import org.NooLab.nativebrowser.app.controller.ExitAction;

import org.NooLab.nativebrowser.app.up.ITexxWindowStartup;
import org.NooLab.nativebrowser.browser.BrowserHostList;
import org.NooLab.nativebrowser.browser.BrowserWorker;
import org.NooLab.nativebrowser.browser.DjBrowserHost;
import org.NooLab.nativebrowser.browser.DjBrowserHostIntf;
import org.NooLab.nativebrowser.browser.DjBrowserListener;
import org.NooLab.nativebrowser.components.BrowserAppRecipientIntf;
import org.NooLab.nativebrowser.components.NativeBrowserCommons;
import org.NooLab.nativebrowser.components.WebBrowserAppMainIntf;
import org.NooLab.nativebrowser.gui.hidden.HiddenWindow;
import org.NooLab.nativebrowser.gui.hidden.HiddenWindowGuiIntf;
import org.NooLab.utilities.logging.LogControl;
import org.NooLab.utilities.logging.PrintLog;
import org.jdesktop.application.SingleFrameApplication;

import chrriis.dj.nativeswing.swtimpl.NativeInterface;
import chrriis.dj.nativeswing.swtimpl.components.JWebBrowser;



/**
 * 
 * Note that this will work ONLY in unframed applications, since the native browser creates a frame,
 * and per application there is only 1 frame allowed.
 * It is not possible to use it as a library in an application that has its own Frame.
 * 
 * Hence, in order to use it, one needs to start its wrapper application as a separate 
 * process (also via ProcessBuilder);
 * 
 * 
 * 
 * 
 *
 */
public class WebBrowserApp 
							extends 
										SingleFrameApplication // JFrame {//
										// Application 
							implements 
										WebBrowserAppMainIntf,
										Observer{
	

	boolean showBasePanel = false; // set to true to see all panels
	float transparencyOfVisible = 0.9f;

	/*
	 * for putting some of the components transparent and other not, we would
	 * have to use JDesktopPane that would contain different frames, to which we
	 * could apply WindowUtils.setWindowTransparent(this, true); (a basic
	 * multiple-frame example can be found here)
	 * 
	 * http://www.roseindia.net/tutorial/java/swing/multipleFrames.html
	 */

	private static JFrame frame;
	private JPanel topPanel = null;

	private WebBrowserApp app; // this

	private HiddenWindow windowGui; // where we define the GUI

	private NativeBrowserCommons appCommons; // object to distribute objects for
											// sharing
	private ITexxAppPropertiesIntf appProperties; // our properties bag

	private int launched = 0;

	// browser stuff
	public JWebBrowser webBrowser; //
	BrowserWorker swingWorker; // sub-classed from SwingWorker, here it is not
								// mandatory,
	// just for filling the browser window with google for user's convenience
	BrowserHostList hostList; // not used! potentially we have many browsers in
								// many logical hosts

	static WebBrowserPublic exposer;
	/**
	 * the logical/organizational home for the browser, organizes the data flow
	 * between decoupled objects
	 */
	DjBrowserHostIntf browserHost; // object organizing the data flow between
									// JWebBrowser (its events) and our
									// application
	private ExitAction exitAction;
	private int loaded;
	private boolean appIsRunning;
	//
	static Arguments argumentsHandler; // reading parameters provided to the
	static BrowserAppRecipientIntf externalObserver;
	private static boolean frameIsVisible = false;


	
	static void getInstance(final String[] args, BrowserAppRecipientIntf externalobserver){
		// this is a different object, but still within the library
		externalObserver = externalobserver;
		internalStart(args);
		
	}
	
	// ----------------------------------------------------
	public static void main(final String[] args) {

		internalStart(args);
		
	}

	private static void internalStart(final String[] args){
		
		
		// if null, then use built-in defaults from resources
		// argumentsHandler = (new Arguments(args)).get();
		
		
		
		NativeInterface.open();

		SwingUtilities.invokeLater(
							new Runnable() {
									public void run() {
											launch(WebBrowserApp.class, args);

									}

							});

		// again: JWebBrowser, especially important for Mac OSX
		try{
			
			NativeInterface.runEventPump();
			
		}catch(Exception e){
		}

	}
	
	// ----------------------------------------------------
	protected WebBrowserApp() throws Exception {
		// this is step 1 of the launching process...

		
		// seedling startup info (such as last session id, last user, whether to
		// load last session...
		ITexxWindowStartup.setApplicationID("itexxwinapp", this.getClass());

		// read properties from file, if such exists... if not, it creates one
		// with defaults
		appProperties = NNBAppProperties.getInstance(ITexxWindowStartup.getProjectBasePath());

		frame = getMainFrame();
		frame.setFocusable(true);
		frame.setEnabled(true);

		frame.setTitle("  iTexx");

		frame.setUndecorated(true);
		
		frame.setVisible(false);
		
		app = this;

		// ..................................

		appCommons = NativeBrowserCommons.getInstance(app);

		appCommons.setFrameReference(frame);

		// this we have to use in order to use only 1 instance of properties
		// we already created the properties on startup in "ITexxWindow2"
		appCommons.setProperties(appProperties);


		// ..................................

		exitAction = new ExitAction(app);
		// exitAction.setActionProvider(appCommons); // closing open queuing loops ??

		frame.addWindowListener(new org.NooLab.nativebrowser.app.controller.ExitListener(exitAction));

		
		// ..................................

		setWindowGui(new HiddenWindow(this));
		getWindowGui().createITexxWindowGui();

		appCommons.setWindowGui(windowGui);
		appCommons.setFrameReference(frame);
	
		/*
		exposer.setReference(this);
		
		appCommons.setExposureClient( exposer ) ;
		*/
		topPanel = windowGui.getTopPanel();
		loaded = 1;
	}

	@Override
	protected void startup() {
		// this is step 2 of the launching process...

		frame = getMainFrame();

		if (topPanel == null) {

			System.out.println("starting (2)...");
			PrintLog.Delay(50);

		}


		setVisible(frameIsVisible);

		
		show(topPanel);
		frame.setVisible(frameIsVisible);
		
		
		
		initBrowserStuff();

	} // startup

	@Override
	public void show(JPanel topPanel) {

		frame.repaint();

		
		super.show(topPanel);
		
	}
	


	@Override
	public void setExternalObserver(WebBrowserPublic webBrowserPublic) {
		// 
		appCommons.setExposureClient( webBrowserPublic );
	}

	@Override
	public void close(int mode) {

		
		appCommons.performClose(app);
		PrintLog.Delay(500);
		
		(new BrowserWorker(null, webBrowser, "[close]")).execute();
		
		if (mode>0){
			exitAction.doThis(null);
			System.exit(0);
		}
		// 
	}
	
	@Override
	public void reset( BrowserAppRecipientIntf externalobserver ){

		try{
			// NativeInterface.close();
		}catch(Exception e){
		}

		// NativeInterface.open();
		// (new BrowserWorker(null, webBrowser, "")).execute();
		
		initBrowserStuff();
	}

	@Override
	public void freeResources() {
		// 
		DjBrowserListener listener;
		
		if (browserHost!=null){
			listener = browserHost.getListener() ;
			browserHost.close();
		}
	}

	public static void setLogControl(int level) {
		// 
		LogControl.Level = level;
	}

	private void initBrowserStuff() {
		//

		// this will be called by "DjBrowserHost" on completion of page loading
		appCommons.createHtmlConsumer();


		// it creates the browser host and the browser itself!
		browserHost = createWebBrowserHostInstance();
											PrintLog.Print(2,"after <createWebBrowserHostInstance>..." );
		// if there was an URL in the arguments, go for it
		
		// (swingWorker = new BrowserWorker(null, webBrowser, "www.google.com")).execute(); 
		// new instance

		// this is directly BrowserAppRecipientIntf, not a Java-Observer....
		// so, we have a simple callback here, which points into the Starter Process
											
		if (externalObserver!=null){
			// this is only defined, if the WebBrowser app is called as a library from another class
											PrintLog.Print(2,"going to provide instance to external app." );
			externalObserver.setBrowserApp( this );
		}
											PrintLog.Print(2,"observer link set, now leaving startup sequence" );

	}

	// ----------------------------------------------------

	@Override
	synchronized public DjBrowserHostIntf createWebBrowserHostInstance() {
		JWebBrowser _webBrowser;

		DjBrowserHostIntf _browserHost;
		
		boolean newWindow;
		if (webBrowser==null){
			_browserHost = new DjBrowserHost(app, 0);
			newWindow=true;
		}else{
			_browserHost = new DjBrowserHost(app,webBrowser, 0);
			newWindow=false;
		}

		// hostList.add((DjBrowserHostIntf) _browserHost);

		// the webbrowser is added to jPanelWebBrowser in
		// DjBrowserListener::establishWebBrowserWindow()
		_webBrowser = _browserHost.getWebBrowser();
		app.webBrowser = _webBrowser;

		app.webBrowser.setBarsVisible(false);
		app.webBrowser.setButtonBarVisible(false);

		System.out.println("[NNB] createWebBrowserHostInstance(), Browser (def) = " + _browserHost.toString());

		
		_browserHost.prepare(app,newWindow);
		return _browserHost;
	}

	@Override
	public void setWebBrowser(JWebBrowser webBrowser) {
		this.webBrowser = webBrowser;
	}

	@Override
	public DjBrowserHostIntf getWebBrowserHostInstance(int index) {
		DjBrowserHostIntf item = null;
		if ((hostList != null) && (index >= 0) && (index < hostList.size())) {
			item = hostList.get(index);
		}else{
			item = this.browserHost;
		}
		return item;
	}

	@Override
	public JWebBrowser getWebBrowser() {
		return webBrowser;
	}

	public void setWindowGui(HiddenWindow windowGui) {
		this.windowGui = windowGui;
	}

	public HiddenWindowGuiIntf getWindowGui() {
		return windowGui;
	}

	public NativeBrowserCommons getAppCommons() {
		return this.appCommons;
	}


	@Override
	public void setAppIsRunning(boolean flag) {
		// 
		appIsRunning = flag ;
	}

	@Override
	public void update(Observable o, Object arg) {

		System.out.println("main app instance of native WebBrowser received an observer message!");
	}

	public static void setVisible(boolean flag) {
		// 
		frameIsVisible = flag;
		
		frame.setVisible(frameIsVisible);
		
		if (frame.isVisible()){
			Dimension d = new Dimension(600,400);
			frame.setSize(d);
			frame.setPreferredSize(d);
			frame.setLocation(800,100);
		}else{

			Dimension d = new Dimension(200,200);
			frame.setSize(d);
			frame.setPreferredSize(d);
			frame.setLocation(8000,5000);
		}

	}
	
	  
	    
	  

}


/*
-prj:base
-homedir:"D:/data/iTexx/app/browser" 
-comm: in-7208,out-7210
-appsecret: adkhf-23487asdf-3487sdfr-324
-name:browser-1
-loglevel:2  
 
 */

class Arguments {

	public float opacity = 0.94f;
	public boolean frameDecor = true;
	String[] argumentStr;

	public Arguments(String args[]) {

		if (args == null) {
			argumentStr = new String[0];
		} else {
			argumentStr = args;
		}

		if (argumentStr.length > 0) {
			parse();
		}
	}

	public Arguments get() {
		//

		return this;
	}

	private void parse() {

	}

}
